/*
 * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.xuexiang.xui_lib.component.grouplist;

import ohos.agp.colors.RgbColor;
import ohos.agp.colors.RgbPalette;
import ohos.agp.components.AbsButton;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.ComponentState;
import ohos.agp.components.DependentLayout;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Image;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.Switch;
import ohos.agp.components.Text;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.components.element.StateElement;
import ohos.agp.components.element.VectorElement;
import ohos.agp.utils.Color;
import ohos.agp.utils.LayoutAlignment;
import ohos.app.Context;

import com.xuexiang.xui_lib.ResourceTable;
import com.xuexiang.xui_lib.util.AttrValue;
import com.xuexiang.xui_lib.util.DisplayUtils;
import com.xuexiang.xui_lib.util.TypedAttrUtils;
import com.xuexiang.xui_lib.util.Utils;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * 作为通用列表 {@link XUIGroupListView} 里的 item 使用，也可以单独使用。
 * 支持以下样式:
 * <ul>
 * <li>通过 {@link #setText(String)} 设置一行文字</li>
 * <li>通过 {@link #setDetailText(String)} 设置一行说明文字, 并通过 {@link #setOrientation(int)} 设置说明文字的位置,
 * 也可以在 xml 中设置。</li>
 * <li>通过 {@link #setAccessoryType(int)} 设置右侧 View 的类型, 可选的类型见 {@link XUICommonListItemAccessoryType},
 * 也可以在 xml 中设置。</li>
 * </ul>
 *
 * @author xuexiang
 * @since 2019/1/3 上午10:52
 */
public class XUICommonListItemView extends DependentLayout implements ComponentContainer.ArrangeListener {
    /**
     * 右侧不显示任何东西
     */
    public static final int ACCESSORY_TYPE_NONE = 0;
    /**
     * 右侧显示一个箭头
     */
    public static final int ACCESSORY_TYPE_CHEVRON = 1;
    /**
     * 右侧显示一个开关
     */
    public static final int ACCESSORY_TYPE_SWITCH = 2;
    /**
     * 自定义右侧显示的 View
     */
    public static final int ACCESSORY_TYPE_CUSTOM = 3;

    /**
     * detailText 在 title 文字的下方
     */
    public static final int VERTICAL = 0;
    /**
     * detailText 在 item 的右方
     */
    public static final int HORIZONTAL = 1;

    /**
     * 红点在左边
     */
    public static final int RED_DOT_POSITION_LEFT = 0;
    /**
     * 红点在右边
     */
    public static final int RED_DOT_POSITION_RIGHT = 1;

    /**
     * 默认 topMargin
     */
    public static final int DEFAULT_MARGIN_TOP = 6;

    /**
     * 数字2
     */
    public static final int VALUE_TWO = 2;

    /**
     * 数字4
     */
    public static final int VALUE_FOUR = 4;

    /**
     * 默认 topMargin
     */
    public static final int RGB_DIVIDER = 234;

    /**
     * switch 默认宽度
     */
    public static final int SWITCH_WIDTH = 140;

    /**
     * switch 默认高度
     */
    public static final int SWITCH_HEIGHT = 80;

    /**
     * text 默认大小
     */
    public static final int TEXT_SIZE = 15;

    /**
     * 自定义view 默认大小
     */
    public static final int VIEW_SIZE = 24;

    /**
     * detailText 默认大小
     */
    public static final int DETAIL_TEXT_SIZE = 13;

    /**
     * switch 默认圆角大小
     */
    public static final int DEFAULT_RADIUS = 35;

    protected Image mImageView;
    protected DirectionalLayout mTextContainer;
    protected Text mTextView;
    protected Text mDetailTextView;
    protected Component mTextDetailSpace;
    protected Component mEmptySpace1;
    protected Component mEmptySpace2;
    protected Switch mSwitch;
    private Image mNewTipViewStub;

    @IntDef({ACCESSORY_TYPE_NONE, ACCESSORY_TYPE_CHEVRON, ACCESSORY_TYPE_SWITCH, ACCESSORY_TYPE_CUSTOM})
    @Retention(RetentionPolicy.SOURCE)
    public @interface XUICommonListItemAccessoryType {
    }

    @IntDef({VERTICAL, HORIZONTAL})
    @Retention(RetentionPolicy.SOURCE)
    public @interface XUICommonListItemOrientation {
    }

    @IntDef({RED_DOT_POSITION_LEFT, RED_DOT_POSITION_RIGHT})
    @Retention(RetentionPolicy.SOURCE)
    public @interface XUICommonListItemRedDotPosition {
    }

    private ComponentContainer mAccessoryView;
    /**
     * Item 右侧的 View 的类型
     */
    @XUICommonListItemAccessoryType
    private int mAccessoryType;

    /**
     * 控制 detailText 是在 title 文字的下方还是 item 的右方
     */
    private int mOrientation = HORIZONTAL;

    /**
     * 控制红点的位置
     */
    @XUICommonListItemRedDotPosition
    private int mRedDotPosition = RED_DOT_POSITION_LEFT;

    private AttrSet attrSet;

    private Image mRedDot;

 /*   *//**
     * 构造器
     *
     * @param context 上下文
     *//*
    public XUICommonListItemView(Context context) {
        this(context, null);
    }
*/
    /**
     * 构造器
     *
     * @param context 上下文
     * @param attrs 属性集
     */
    public XUICommonListItemView(Context context, AttrSet attrs) {
        this(context, attrs, null);
    }

    /**
     * 构造器
     *
     * @param context 上下文
     * @param attrs 属性集
     * @param defStyleAttr 默认属性
     */
    public XUICommonListItemView(Context context, AttrSet attrs, String defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    }

    /**
     * 初始化
     *
     * @param context 上下文
     * @param attrs 属性集
     * @param defStyleAttr 默认属性
     */
    protected void init(Context context, AttrSet attrs, String defStyleAttr) {
        attrSet = attrs;
        LayoutScatter.getInstance(context).parse(ResourceTable.Layout_xui_layout_common_list_item, this, true);

        final int initTitleColor = TypedAttrUtils.getIntColor(attrs,
            "xui_commonList_titleColor", ResourceTable.Color_xui_config_color_gray_1);
        final int initDetailColor = TypedAttrUtils.getIntColor(attrs,
            "xui_commonList_detailColor", ResourceTable.Color_xui_config_color_gray_5);

        mImageView = (Image) findComponentById(ResourceTable.Id_group_list_item_imageView);
        mTextContainer = (DirectionalLayout) findComponentById(ResourceTable.Id_group_list_item_textContainer);
        mTextView = (Text) findComponentById(ResourceTable.Id_group_list_item_textView);
        mTextView.setTextColor(new Color(getContext().getColor(initTitleColor)));
        mRedDot = (Image) findComponentById(ResourceTable.Id_group_list_item_tips_dot);
        mNewTipViewStub = (Image) findComponentById(ResourceTable.Id_group_list_item_tips_new);
        mDetailTextView = (Text) findComponentById(ResourceTable.Id_group_list_item_detailTextView);
        mTextDetailSpace = findComponentById(ResourceTable.Id_group_list_item_space);
        mEmptySpace1 = findComponentById(ResourceTable.Id_group_list_space1);
        mEmptySpace2 = findComponentById(ResourceTable.Id_group_list_space2);
        mDetailTextView.setTextColor(new Color(getContext().getColor(initDetailColor)));
        DirectionalLayout.LayoutConfig config = (DirectionalLayout.LayoutConfig) mDetailTextView.getLayoutConfig();
        @XUICommonListItemOrientation int orientation = AttrValue.get(attrs, "xui_orientation", HORIZONTAL);
        if (orientation == VERTICAL) {
            config.setMarginTop(DisplayUtils.vp2px(getContext(), DEFAULT_MARGIN_TOP));
        } else {
            config.setMarginTop(DisplayUtils.vp2px(getContext(), 0));
        }
        mAccessoryView = (ComponentContainer) findComponentById(ResourceTable.Id_group_list_item_accessoryView);

        // 设置item分割线
        Component component = new Component(getContext());
        component.setLayoutConfig(new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT, 1));
        ShapeElement shapeElement = new ShapeElement();
        shapeElement.setRgbColor(new RgbColor(RGB_DIVIDER, RGB_DIVIDER, RGB_DIVIDER));
        component.setBackground(shapeElement);
        DependentLayout dependentLayout = (DependentLayout) findComponentById(ResourceTable.Id_dependentLayout);
        dependentLayout.addComponent(component);
        setOrientation(orientation);
        @XUICommonListItemAccessoryType int accessoryType = AttrValue.get(attrs,
            "xui_accessory_type", ACCESSORY_TYPE_NONE);
        setAccessoryType(accessoryType);
        setArrangeListener(this);
    }

    public void updateImageViewLc(LayoutParamConfig lpConfig) {
        if (lpConfig != null) {
            LayoutConfig lp = (LayoutConfig) mImageView.getLayoutConfig();
            mImageView.setLayoutConfig(lpConfig.onConfig(lp));
        }
    }

    public void setImageElement(int image) {
        if (image == 0) {
            mImageView.setVisibility(Component.HIDE);
        } else {
            mImageView.setPixelMap(image);
            mImageView.setVisibility(Component.VISIBLE);
        }
    }

    public void setRedDotPosition(@XUICommonListItemRedDotPosition int redDotPosition) {
        mRedDotPosition = redDotPosition;
        postLayout();
    }

    public String getText() {
        return mTextView.getText();
    }

    public void setText(String text) {
        mTextView.setText(text);
        if (Utils.isNullOrEmpty(text)) {
            mTextView.setVisibility(Component.HIDE);
        } else {
            mTextView.setVisibility(Component.VISIBLE);
        }
    }

    /**
     * 切换是否显示小红点
     *
     * @param isShow 是否显示小红点
     */
    public void showRedDot(boolean isShow) {
        showRedDot(isShow, true);
    }

    public void showRedDot(boolean isShow, boolean configToShow) {
        mRedDot.setVisibility((isShow && configToShow) ? VISIBLE : HIDE);
    }

    /**
     * 切换是否显示更新提示
     *
     * @param isShow 是否显示更新提示
     */
    public void showNewTip(boolean isShow) {
        if (isShow) {
            mNewTipViewStub.setVisibility(VISIBLE);
            mRedDot.setVisibility(HIDE);
        } else {
            if (mNewTipViewStub != null && mNewTipViewStub.getVisibility() == VISIBLE) {
                mNewTipViewStub.setVisibility(HIDE);
            }
        }
    }

    public CharSequence getDetailText() {
        return mDetailTextView.getText();
    }

    public void setDetailText(String text) {
        mDetailTextView.setText(text);
        if (Utils.isNullOrEmpty(text)) {
            mDetailTextView.setVisibility(Component.HIDE);
        } else {
            mDetailTextView.setVisibility(Component.VISIBLE);
        }
    }

    public int getOrientation() {
        return mOrientation;
    }

    public void setOrientation(@XUICommonListItemOrientation int orientation) {
        mOrientation = orientation;
        DirectionalLayout.LayoutConfig spaceLp = (DirectionalLayout.LayoutConfig) mTextDetailSpace.getLayoutConfig();

        // 默认文字是水平布局的
        if (mOrientation == VERTICAL) {
            mTextContainer.setOrientation(DirectionalLayout.VERTICAL);
            mTextContainer.setAlignment(LayoutAlignment.LEFT);
            spaceLp.width = ComponentContainer.LayoutConfig.MATCH_CONTENT;
            spaceLp.height = DisplayUtils.vp2px(getContext(), VALUE_FOUR);
            spaceLp.weight = 0;
            mTextView.setTextSize(DisplayUtils.vp2px(getContext(), TypedAttrUtils.getDimensionPixelSize(attrSet,
                "xui_common_list_item_title_v_text_size", TEXT_SIZE)));
            mDetailTextView.setTextSize(DisplayUtils.vp2px(getContext(), TypedAttrUtils.getDimensionPixelSize(attrSet,
                "xui_common_list_item_detail_v_text_size", DETAIL_TEXT_SIZE)));
            mTextDetailSpace.setVisibility(HIDE);
            mEmptySpace1.setVisibility(VISIBLE);
            mEmptySpace2.setVisibility(VISIBLE);
        } else {
            mTextContainer.setOrientation(DirectionalLayout.HORIZONTAL);
            mTextContainer.setAlignment(LayoutAlignment.VERTICAL_CENTER);
            spaceLp.width = 0;
            spaceLp.height = 0;
            spaceLp.weight = 1;
            mTextView.setTextSize(DisplayUtils.vp2px(getContext(), TypedAttrUtils.getDimensionPixelSize(attrSet,
                "xui_common_list_item_title_h_text_size", TEXT_SIZE)));
            mDetailTextView.setTextSize(DisplayUtils.vp2px(getContext(), TypedAttrUtils.getDimensionPixelSize(attrSet,
                "xui_common_list_item_detail_h_text_size", DETAIL_TEXT_SIZE)));
        }
    }

    public int getAccessoryType() {
        return mAccessoryType;
    }

    /**
     * 设置右侧 View 的类型。
     * <p>
     * 注意如果 type 为 {@link #ACCESSORY_TYPE_SWITCH}, 那么 switch 的切换事件应该 {@link #getSwitch()} 后用
     * {@link Switch#setCheckedStateChangedListener(AbsButton.CheckedStateChangedListener)} 来监听
     * </p>
     *
     * @param type 见 {@link XUICommonListItemAccessoryType}
     */
    public void setAccessoryType(@XUICommonListItemAccessoryType int type) {
        mAccessoryView.removeAllComponents();
        mAccessoryType = type;

        switch (type) {
            // 向右的箭头
            case ACCESSORY_TYPE_CHEVRON:
                Image tempImage = getAccessoryImageView();
                tempImage.setImageElement(new VectorElement(getContext(), ResourceTable.Graphic_xui_icon_chevron));
                mAccessoryView.addComponent(tempImage);
                mAccessoryView.setVisibility(VISIBLE);
                break;

            // switch开关
            case ACCESSORY_TYPE_SWITCH:
                if (mSwitch == null) {
                    mSwitch = new Switch(getContext());
                    mSwitch.setComponentSize(SWITCH_WIDTH, SWITCH_HEIGHT);
                    setSwitchStyle();

                    // disable掉且不可点击，然后通过整个item的点击事件来toggle开关的状态
                    mSwitch.setClickable(false);
                    mSwitch.setEnabled(false);
                }
                mAccessoryView.addComponent(mSwitch);
                mAccessoryView.setVisibility(VISIBLE);
                break;

            // 自定义View
            case ACCESSORY_TYPE_CUSTOM:
                mAccessoryView.setComponentSize(DisplayUtils.vp2px(getContext(), VIEW_SIZE),
                    DisplayUtils.vp2px(getContext(), VIEW_SIZE));
                mAccessoryView.setVisibility(VISIBLE);
                break;

            // 清空所有accessoryView
            case ACCESSORY_TYPE_NONE:
                mAccessoryView.setVisibility(HIDE);
                break;
            default:
                break;
        }
    }

    /**
     * 设置switch样式
     */
    private void setSwitchStyle() {
        // 开启状态下滑块的样式
        ShapeElement elementThumbOn = new ShapeElement();
        elementThumbOn.setShape(ShapeElement.OVAL); // 设置形状-圆形
        elementThumbOn.setRgbColor(RgbPalette.WHITE); // 设置颜色

        // 开启状态下轨迹样式
        ShapeElement elementTrackOn = new ShapeElement();
        elementTrackOn.setShape(ShapeElement.RECTANGLE); // 设置形状-矩形
        elementTrackOn.setRgbColor(new RgbColor(38, 172, 217));
        elementTrackOn.setCornerRadius(DEFAULT_RADIUS);

        // 关闭状态下轨迹样式
        ShapeElement elementTrackOff = new ShapeElement();
        elementTrackOff.setShape(ShapeElement.RECTANGLE);
        elementTrackOff.setRgbColor(RgbPalette.GRAY);
        elementTrackOff.setCornerRadius(DEFAULT_RADIUS);

        mSwitch.setTrackElement(trackElementInit(elementTrackOn, elementTrackOff)); // 设置轨迹
        mSwitch.setThumbElement(thumbElementInit(elementThumbOn, elementThumbOn)); // 设置滑块
    }

    /**
     * 轨迹样式
     *
     * @param on 选中时轨迹
     * @param off 未选中时轨迹
     * @return 轨迹样式stateElement
     */
    private StateElement trackElementInit(ShapeElement on, ShapeElement off) {
        StateElement trackElement = new StateElement();
        trackElement.addState(new int[]{ComponentState.COMPONENT_STATE_CHECKED}, on);
        trackElement.addState(new int[]{ComponentState.COMPONENT_STATE_EMPTY}, off);
        return trackElement;
    }

    /**
     * 滑块样式
     *
     * @param on 选中时滑块
     * @param off 未选中时滑块
     * @return 滑块样式stateElement
     */
    private StateElement thumbElementInit(ShapeElement on, ShapeElement off) {
        StateElement thumbElement = new StateElement();
        thumbElement.addState(new int[]{ComponentState.COMPONENT_STATE_CHECKED}, on);
        thumbElement.addState(new int[]{ComponentState.COMPONENT_STATE_EMPTY}, off);
        return thumbElement;
    }

    private ComponentContainer.LayoutConfig getAccessoryLayoutParams() {
        return new ComponentContainer.LayoutConfig(ComponentContainer.LayoutConfig.MATCH_CONTENT,
            ComponentContainer.LayoutConfig.MATCH_CONTENT);
    }

    private Image getAccessoryImageView() {
        Image resultImageView = new Image(getContext());
        resultImageView.setLayoutConfig(getAccessoryLayoutParams());
        resultImageView.setScaleMode(Image.ScaleMode.CENTER);
        return resultImageView;
    }

    public Text getTextView() {
        return mTextView;
    }

    public Text getDetailTextView() {
        return mDetailTextView;
    }

    public Switch getSwitch() {
        return mSwitch;
    }

    public ComponentContainer getAccessoryContainerView() {
        return mAccessoryView;
    }

    /**
     * 添加自定义的 Accessory View
     *
     * @param component 自定义的 Accessory View
     */
    public void addAccessoryCustomView(Component component) {
        if (mAccessoryType == ACCESSORY_TYPE_CUSTOM) {
            mAccessoryView.addComponent(component);
        }
    }

    @Override
    public boolean onArrange(int i, int i1, int i2, int i3) {
        // 红点的位置
        if (mRedDot != null && mRedDot.getVisibility() == Component.VISIBLE) {
            int top = getHeight() / VALUE_TWO - mRedDot.getEstimatedHeight() / VALUE_TWO;
            int textLeft = mTextContainer.getLeft();
            int left;

            if (mRedDotPosition == RED_DOT_POSITION_LEFT) {
                // 红点在左
                float textWidth = mTextView.getMaxTextWidth(); // 文字宽度
                left = (int) (textLeft + textWidth + DisplayUtils.vp2px(getContext(), VALUE_FOUR)); // 在原来红点位置的基础上右移
            } else if (mRedDotPosition == RED_DOT_POSITION_RIGHT) {
                // 红点在右
                left = textLeft + mTextContainer.getWidth() - mRedDot.getEstimatedWidth();
            } else {
                return false;
            }

            mRedDot.arrange(left,
                top,
                left + mRedDot.getEstimatedWidth(),
                top + mRedDot.getEstimatedHeight());
        }

        // New的位置
        if (mNewTipViewStub != null && mNewTipViewStub.getVisibility() == Component.VISIBLE) {
            int textLeft = mTextContainer.getLeft();
            float textWidth = mTextView.getMaxTextWidth(); // 文字宽度
            int left = (int) (textLeft + textWidth + DisplayUtils.vp2px(getContext(), VALUE_FOUR)); // 在原来红点位置的基础上右移
            int top = getHeight() / VALUE_TWO - mNewTipViewStub.getEstimatedHeight() / VALUE_TWO;
            mNewTipViewStub.arrange(left,
                top,
                left + mNewTipViewStub.getEstimatedWidth(),
                top + mNewTipViewStub.getEstimatedHeight());
        }
        return false;
    }

    public interface LayoutParamConfig {
        DependentLayout.LayoutConfig onConfig(DependentLayout.LayoutConfig lc);
    }
}
